home *** CD-ROM | disk | FTP | other *** search
- /* Plain Vanilla Posting II
-
- Copyright 1990 Plain Vanilla Corporation
- P.O. Box 4493, San Diego CA 92164
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <setjmp.h>
- #include <string.h>
- #include <dos.h>
- #include <alloc.h>
-
- static char id[] = {0x17,0xFD,0x46,0x0F,0x74,0xB3};
- static char s1[] = "Changeable journal name (0=no, 1=yes)";
- static int changeable_journal_name = 0;
- static char sx[] = "";
-
- #define MAXIMUM_NAME_OR_FILESPEC_LENGTH 64
- #define MAXIMUM_FILESPEC_LENGTH 64
- #define MAXIMUM_NAME_LENGTH 40
- #define JOURNAL_NAME_LENGTH 12
-
- typedef long amount_type;
-
- extern amount_type multiply_10(amount_type);
- extern amount_type divide_10(amount_type);
- extern amount_type sum(amount_type, amount_type);
- extern amount_type negative(amount_type);
- extern int remainder_10(amount_type);
-
- #define AMOUNT_WIDTH 13
-
- #define isdebit(x) ((x)>0)
- #define iscredit(x) ((x)<0)
- #define iszero(x) ((x)==0)
- #define zero 0L
-
- static char *edit_line_number(unsigned n)
- {
- static char s[] = {'x','x','x','x',0};
- int i;
- for (i=3; i>=0; i--, n/=10) s[i] = n%10+'0';
- return s;
- }
-
- /* case-insensitive strcmp() */
-
- static int ci_strcmp(char *s, char *t)
- {
- while (*s!=0 && toupper(*s)==toupper(*t)) {s++; t++;}
- return toupper(*s)-toupper(*t);
- }
-
- static struct
- {
- jmp_buf jump_buffer;
- char *message;
- char *name;
- int level;
- } err;
-
- struct file
- {
- int c;
- FILE *fp;
- char *command_line_argument_pointer;
- unsigned line;
- int indented, new_entry;
- char specs[MAXIMUM_FILESPEC_LENGTH+1];
- };
-
- static struct file source;
-
- static FILE *output;
- static char output_specs[MAXIMUM_FILESPEC_LENGTH+1];
-
- #define error() setjmp(err.jump_buffer)
-
- static void error_message(void)
- {
- if (source.specs[0]!=0) fputs(source.specs, stdout);
- if (source.line!=0)
- {
- putchar(':');
- fputs(edit_line_number(source.line), stdout);
- }
- putchar(' ');
- fputs(err.message,stdout);
- if (err.name!=NULL)
- {
- fputs(" -- ", stdout);
- fputs(err.name, stdout);
- }
- putchar('\n');
- err.level = 1;
- }
-
- static void error_exit(void)
- {
- error_message();
- exit(err.level);
- }
-
- static void raise_error_with_name(char *message, char *name)
- {
- err.message = message;
- err.name = name;
- longjmp(err.jump_buffer, 1);
- }
-
- void raise_error(char *message)
- {
- raise_error_with_name(message, NULL);
- }
-
- static void declare_error_with_name(char *message, char *name)
- {
- err.message = message;
- err.name = name;
- error_message();
- }
-
- static void declare_error(char *message)
- {
- declare_error_with_name(message, NULL);
- }
-
- static void open_source_file(char *specs)
- {
- if (specs[0]=='[')
- {
- source.command_line_argument_pointer = specs+1;
- specs = "[]";
- }
- else
- {
- if (specs[0]=='+') specs++;
- source.fp = fopen(specs,"r");
- if (source.fp==NULL)
- raise_error_with_name("Can't open source file", specs);
- source.command_line_argument_pointer = NULL;
- }
- strcpy(source.specs, specs);
- source.c = '\n';
- source.line = 0;
- }
-
- static void read_character(void)
- {
- if (source.c!=EOF)
- {
- if (source.c=='\n' && source.line<9999) source.line++;
- if (source.command_line_argument_pointer==NULL)
- source.c = getc(source.fp);
- else
- {
- source.c = *source.command_line_argument_pointer++;
- if (source.c==0) source.c = EOF;
- }
- }
- }
-
- static void close_source_file(void)
- {
- if (source.command_line_argument_pointer==NULL);
- fclose(source.fp);
- }
-
- static void invalid_amount(void)
- {
- raise_error("Invalid dollar amount");
- }
-
- static void skip_spaces(void)
- {
- while (source.c==' ' || source.c=='\t') read_character();
- }
-
- static void next_line(void)
- {
- source.indented = source.new_entry = 0;
- while (1)
- {
- source.indented = 0;
- while (source.c!='\n')
- {
- if (source.c==EOF) {source.new_entry = 1; return;}
- read_character();
- }
- read_character();
- if (source.c==' ' || source.c=='\t') source.indented = 1;
- skip_spaces();
- if (isalpha(source.c)) break;
- if (source.c=='\n' || source.c==EOF) source.new_entry = 1;
- else if (source.c!='*') declare_error("Questionable journal line");
- }
- }
-
- static amount_type read_amount(void)
- {
- int commas = 0;
- int cents = 0;
- int position = 0;
- int nothing = 1;
- amount_type amount;
- amount = zero;
- skip_spaces();
- while (1)
- {
- if (source.c==',')
- {
- if (nothing || cents || commas && position!=4 || !commas && position>3)
- invalid_amount();
- commas = 1;
- position = 0;
- commas = 1;
- }
- else if (source.c=='.')
- {
- if (nothing || cents || commas && position!=4) invalid_amount();
- cents = 1;
- commas = 0;
- position = 0;
- }
- else if (isdigit(source.c))
- {
- nothing = 0;
- if (commas && position==4 || cents && position==3) invalid_amount();
- amount = sum(multiply_10(amount), (amount_type)(source.c-'0'));
- }
- else break;
- read_character();
- position++;
- }
- if (nothing || cents && position!=3 || commas && position!=4)
- invalid_amount();
- if (!cents)
- {
- amount = multiply_10(amount);
- amount = multiply_10(amount);
- }
- return amount;
- }
-
-
- static unsigned read_number(void)
- {
- int no_number = 1;
- unsigned number = 0;
- skip_spaces();
- while (isdigit(source.c))
- {
- if (number>6552) {number = 0xFFFF; break;}
- number = 10*number + source.c - '0';
- no_number = 0;
- read_character();
- }
- if (no_number) number = 0xFFFF;
- return number;
- }
-
- static int invalid_file_character(int c)
- {
- return c<=' ' || c=='"' || c=='/' || c=='[' || c==']' ||
- c=='|' || c=='<' || c=='>' || c=='+' || c=='=' ||
- c==';' || c==',';
- }
-
- static void read_specs(char *specs)
- {
- int i = 0;
- skip_spaces();
- if (source.c=='+')
- {
- specs[i++] = '+';
- read_character();
- }
- if (invalid_file_character(source.c))
- raise_error("Invalid or missing file specifications");
- while (!invalid_file_character(source.c))
- {
- if (i<MAXIMUM_FILESPEC_LENGTH) specs[i++] = source.c;
- read_character();
- }
- specs[i] = 0;
- skip_spaces();
- }
-
- static void read_name(char *name)
- {
- int i = 0;
- skip_spaces();
- if (!isalpha(source.c))
- raise_error("Invalid or missing name");
- do
- {
- do
- {
- if (i<MAXIMUM_NAME_LENGTH) name[i++] = source.c;
- read_character();
- } while (isalnum(source.c) || source.c=='/');
- if (i<MAXIMUM_NAME_LENGTH) name[i++] = ' ';
- skip_spaces();
- } while (isalpha(source.c));
- if (name[i-1]==' ') i--;
- name[i] = 0;
- }
-
- static void *get_memory(int n)
- {
- void *g = malloc((unsigned long)n);
- char *t;
- if (g==NULL)
- {
- puts("\nInsufficient memory");
- exit(1);
- }
- for (t=g; n>0; n--) *t++ = 0;
- return g;
- }
-
- static void open_output_file(char *specs)
- {
- if (specs==NULL) output = stdout;
- else
- {
- if (specs[0]=='+') output = fopen(specs+1,"a");
- else output = fopen(specs,"w");
- if (output==NULL) raise_error_with_name("Can't open output file", specs);
- strcpy(output_specs, specs);
- }
- }
-
- static void close_output_file(void)
- {
- if (output!=stdout && output!=NULL) fclose(output);
- output = NULL;
- }
-
- static void write_character(int c)
- {
- if (output==stdout) putchar(c);
- else if (putc(c,output)==EOF)
- {
- close_output_file();
- raise_error_with_name("File write error", output_specs);
- }
- }
-
- static void write_string(char *s)
- {
- while (*s!=0) write_character(*s++);
- }
-
- static void write_amount(amount_type amount, int trim)
- {
- char s[AMOUNT_WIDTH+1];
- register char *t = s+sizeof(s);
- *--t = 0;
- *--t = remainder_10(amount)+'0'; amount = divide_10(amount);
- *--t = remainder_10(amount)+'0'; amount = divide_10(amount);
- *--t = '.';
- do
- {
- if (t==s+7 || t==s+3) *--t = ',';
- *--t = remainder_10(amount)+'0';
- amount = divide_10(amount);
- } while (!iszero(amount));
- if (trim>=0)
- {
- if (t<s+trim) declare_error("Digit trimmed");
- while (t>s+trim) *--t = ' ';
- }
- write_string(t);
- }
-
- static void write_repeated_characters(int character, int trim)
- {
- int count;
- for (count=trim; count<AMOUNT_WIDTH; count++) write_character(character);
- }
-
- typedef struct
- {
- unsigned day : 5;
- unsigned month : 4;
- unsigned year : 7;
- } packed_date;
-
- static void invalid_date(void)
- {
- raise_error("Invalid date");
- }
-
- static unsigned get_date_number(void)
- {
- unsigned n = read_number();
- if (n>2049) invalid_date();
- return n;
- }
-
- static packed_date read_date(void)
- {
- packed_date date;
- unsigned day, month, year;
- static int DAYS_IN_MONTH[13] = {0,31,29,31,30,31,30,31,31,30,31,30,31};
- skip_spaces();
- if (isdigit(source.c))
- {
- int delimiter;
- month = get_date_number();
- delimiter = source.c; read_character();
- if (delimiter!='/' && delimiter!='-' && delimiter!='.') invalid_date();
- day = get_date_number();
- if (source.c!=delimiter) invalid_date();
- read_character();
- year = get_date_number();
- }
- else if (isalpha(source.c))
- {
- static char *MONTH_NAME[] =
- {
- "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL",
- "AUG", "SEP", "OCT", "NOV", "DEC"
- };
- char month_name[4];
- int i = 0;
- while (isalpha(source.c) || source.c=='.')
- {
- if (i<3) month_name[i++] = toupper(source.c);
- read_character();
- }
- month_name[i] = 0;
- for (i=0; i<12; i++) if (strcmp(month_name, MONTH_NAME[i])==0) break;
- month = i+1;
- if (source.c=='.') read_character();
- day = get_date_number();
- if (source.c==',') read_character();
- year = get_date_number();
- }
- else invalid_date();
- if (year<50) year += 2000;
- else if (year>79 && year<100) year += 1900;
- else if (year<1980 || year>2049) invalid_date();
- date.year = year-1980;
- if (month==0 || month>12 || day==0 || day>DAYS_IN_MONTH[month] ||
- month==2 && day==29 && year%4!=0)
- invalid_date();
- date.month = month;
- date.day = day;
- return date;
- }
-
- struct journal
- {
- char name[JOURNAL_NAME_LENGTH+1];
- };
-
- struct ledger_line
- {
- struct ledger_line *next;
- packed_date date;
- struct journal journal;
- unsigned line;
- amount_type amount;
- };
-
- enum table_type {ACCOUNT, AMOUNT};
-
- struct table
- {
- struct table *next;
- enum table_type type;
- union
- {
- struct
- {
- struct ledger_line *last_line;
- struct ledger_line *first_line;
- } account;
- amount_type amount;
- } x;
- char name[MAXIMUM_NAME_LENGTH+1];
- };
-
- static struct table *first_table_entry = NULL;
- static struct table *last_table_entry;
-
- static char company_name[MAXIMUM_NAME_LENGTH+1];
- static char name[MAXIMUM_NAME_OR_FILESPEC_LENGTH+1];
- static struct journal current_journal;
- static packed_date current_date;
- static amount_type balance;
- static amount_type total;
-
- static void write_two_digits(unsigned n)
- {
- write_character(n/10+'0');
- write_character(n%10+'0');
- }
-
- static void write_name(char *s)
- {
- int i, j;
- for (i=0; i<MAXIMUM_NAME_LENGTH+1; i++)
- write_character(*s==0 ? ' ' : *s++);
- }
-
- static amount_type account_balance(struct table *p)
- {
- amount_type amount;
- if (p->type==ACCOUNT)
- {
- struct ledger_line *q;
- amount = zero;
- for (q=p->x.account.first_line; q!=NULL; q=q->next)
- amount = sum(amount, q->amount);
- }
- else amount = p->x.amount;
- return amount;
- }
-
- static struct table *look_for_table_entry(char *name)
- {
- struct table *p;
- for (p=first_table_entry; p!=NULL; p=p->next)
- if (ci_strcmp(name,p->name)==0) break;
- return p;
- }
-
- static struct table *find_table_entry(char *name)
- {
- struct table *p = look_for_table_entry(name);
- if (p==NULL)
- raise_error_with_name("Undefined ledger account or non-ledger amount",
- name);
- return p;
- }
-
- static struct table *new_table_entry(char *name)
- {
- struct table *p;
- p = look_for_table_entry(name);
- if (p!=NULL)
- raise_error_with_name("Duplicate ledger account or non-ledger amount name",
- name);
- p = get_memory(sizeof(struct table)-MAXIMUM_NAME_LENGTH+strlen(name));
- if (first_table_entry==NULL) first_table_entry = p;
- else last_table_entry->next = p;
- last_table_entry = p;
- strcpy(p->name, name);
- return p;
- }
-
- static void write_date(packed_date date)
- {
- write_two_digits(date.month);
- write_character('/');
- write_two_digits(date.day);
- write_character('/');
- write_two_digits((date.year+80)%100);
- }
-
- static void write_extended_date(packed_date date)
- {
- static char *MONTH_NAME[] =
- {
- "? ", "January ", "February ", "March ", "April ", "May ", "June ",
- "July ", "August ", "September ", "October ", "November ", "December"
- };
- write_string(MONTH_NAME[date.month]);
- if (date.day>9) write_character(date.day/10+'0');
- write_character(date.day%10+'0');
- write_string(date.year<2000-1980 ? ", 19" : ", 20");
- write_two_digits((date.year+80)%100);
- }
-
- static void post(amount_type amount, struct table *p)
- {
- struct ledger_line *q;
- if (p->type==AMOUNT)
- raise_error_with_name("Attempt to post to non-ledger amount", p->name);
- balance = sum(balance, amount);
- q = get_memory(sizeof(struct ledger_line));
- q->date = current_date;
- q->journal = current_journal;
- q->line = source.line;
- q->amount = amount;
- if (p->x.account.first_line==NULL) p->x.account.first_line = q;
- else p->x.account.last_line->next = q;
- p->x.account.last_line = q;
- }
-
- static void check_company_name(char *name)
- {
- if (company_name[0]==0) strcpy(company_name,name);
- else if (ci_strcmp(name,company_name)!=0)
- raise_error("Company name mismatch");
- }
-
- static void company_name_required(void)
- {
- if (company_name[0]==0)
- declare_error("Company name not previously recorded");
- }
-
- static void read_ledger(char *specs)
- {
- struct file save_source;
- save_source = source;
- if (error())
- {
- error_message();
- if (source.fp!=NULL) close(source.fp);
- source = save_source;
- return;
- }
- open_source_file(specs);
- read_character();
- read_name(name);
- check_company_name(name);
- while (1)
- {
- struct table *p;
- while (source.c==' ' || source.c=='\t' || source.c=='\n') read_character();
- if (source.c==EOF) break;
- read_name(name);
- p = new_table_entry(name);
- p->type = ACCOUNT;
- while (1)
- {
- struct ledger_line *q;
- int credit = 0;
- while (source.c==' ' || source.c=='\t' || source.c=='\n')
- read_character();
- if (isalpha(source.c) || source.c==EOF) break;
- q = get_memory(sizeof(struct ledger_line));
- q->date = read_date();
- {
- int i;
- read_name(name);
- for (i=0; i<JOURNAL_NAME_LENGTH; i++)
- q->journal.name[i] = name[i];
- }
- q->line = read_number();
- if (q->line>9999) raise_error("Invalid ledger line");
- skip_spaces();
- if (source.c=='(') {credit = 1; read_character();}
- q->amount = read_amount();
- if (credit)
- {
- if (source.c!=')') raise_error("Invalid ledger line");
- q->amount = negative(q->amount);
- read_character();
- }
- if (p->x.account.first_line==NULL) p->x.account.first_line = q;
- else p->x.account.last_line->next = q;
- p->x.account.last_line = q;
- balance = sum(balance, q->amount);
- }
- }
- close_source_file();
- if (!iszero(balance))
- raise_error("Books are out of balance");
- source = save_source;
- }
-
- static void write_ledger(char *specs)
- {
- struct table *p;
- open_output_file(specs);
- if (error())
- {
- error_message();
- close_output_file();
- return;
- }
- write_string(company_name); write_character('\n');
- for (p=first_table_entry; p!=NULL; p=p->next) if (p->type==ACCOUNT)
- {
- struct ledger_line *q;
- write_character('\n');
- write_string(p->name);
- write_character('\n');
- for (q=p->x.account.first_line; q!=NULL; q=q->next)
- {
- int i;
- unsigned n;
- int credit = 0;
- char *t;
- amount_type amount = q->amount;
- write_string(" ");
- write_date(q->date);
- write_character(' ');
- for (i=0, t=q->journal.name; i<JOURNAL_NAME_LENGTH; i++)
- write_character(*t!=0 ? *t++ : ' ');
- write_character(' ');
- write_string(edit_line_number(q->line));
- write_character(' ');
- if (iscredit(amount))
- {
- credit = 1;
- write_character('(');
- amount = negative(amount);
- }
- else write_character(' ');
- write_amount(amount,0);
- if (credit) write_character(')');
- write_character('\n');
- }
- }
- close_output_file();
- }
-
- static void scan_away_insertion(void)
- {
- while (source.c!='}' && source.c!='\n' && source.c!=EOF) read_character();
- if (source.c=='}') read_character();
- }
-
- static void report(char *specs1, char *specs2, int trim)
- {
- struct file save_source;
- open_output_file(specs2);
- save_source = source;
- if (error())
- {
- error_message();
- if (specs1!=NULL) close_source_file();
- source = save_source;
- close_output_file();
- return;
- }
- if (specs1!=NULL)
- {
- open_source_file(specs1);
- read_character();
- }
- while (source.c!=EOF && !(specs1==NULL && source.c=='\n') && output!=NULL)
- {
- amount_type amount;
- int parentheses = 0;
- if (error())
- {
- error_message();
- if (specs1!=NULL) close_source_file();
- source = save_source;
- close_output_file();
- return;
- }
- while (source.c!='{' && source.c!=EOF && !(specs1==NULL && source.c=='\n'))
- {
- write_character(source.c);
- read_character();
- }
- if (source.c==EOF || specs1==NULL && source.c=='\n') break;
- read_character();
- if (error())
- {
- error_message();
- scan_away_insertion();
- continue;
- }
- skip_spaces();
- if (source.c=='}' || source.c=='-' || source.c=='=')
- {
- int i;
- write_character(' ');
- write_repeated_characters(source.c=='}' ? ' ' : source.c, trim);
- write_character(' ');
- scan_away_insertion();
- continue;
- }
- read_name(name);
- if (source.c==':')
- {
- if (ci_strcmp(name,"COMPANY")==0) write_string(company_name);
- else if (ci_strcmp(name,"DATE")==0) write_extended_date(current_date);
- else raise_error("Invalid \"blank\"");
- scan_away_insertion();
- continue;
- }
- amount = account_balance(find_table_entry(name));
- if (source.c!=',') raise_error("Missing dr/cr");
- read_character();
- read_name(name);
- if (ci_strcmp(name,"DR")==0)
- {
- if (iscredit(amount))
- {
- parentheses = 1;
- amount = negative(amount);
- }
- }
- else if (ci_strcmp(name,"CR")==0)
- {
- if (!isdebit(amount)) amount = negative(amount);
- else parentheses = 1;
- }
- else raise_error("Missing cr/dr");
- if (source.c!='}') raise_error("Missing right brace");
- read_character();
- write_character(parentheses ? '(' : ' ');
- write_amount(amount, trim);
- write_character(parentheses ? ')' : ' ');
- }
- close_output_file();
- if (specs1!=NULL)
- {
- close_source_file();
- source = save_source;
- }
- }
-
- static void journal(char *specs)
- {
- struct file save_source;
- struct journal save_journal;
- save_source = source;
- save_journal = current_journal;
- balance = zero;
- total = zero;
- if (error())
- {
- error_message();
- if (source.fp!=NULL) close(source.fp);
- source = save_source;
- current_journal = save_journal;
- return;
- }
- open_source_file(specs);
- current_journal.name[0] = 0;
- while (1)
- {
- next_line();
- if (source.new_entry)
- {
- if (balance!=0)
- {
- declare_error("Unbalanced entry");
- balance = 0;
- }
- if (total!=0)
- {
- declare_error("Unfinished total");
- total = 0;
- }
- }
- if (source.c==EOF) break;
- if (error()) {error_message(); continue;}
- read_name(name);
- if (source.c==':')
- {
- read_character();
- if (ci_strcmp(name,"JOURNAL")==0)
- {
- int i;
- skip_spaces();
- read_name(name);
- name[JOURNAL_NAME_LENGTH] = 0;
- if (name[JOURNAL_NAME_LENGTH-1]==' ')
- name[JOURNAL_NAME_LENGTH-1] = 0;
- if (!changeable_journal_name && current_journal.name[0]!=0 &&
- ci_strcmp(current_journal.name,name)!=0)
- declare_error_with_name("Journal name changed within file", name);
- strcpy(current_journal.name, name);
- }
- else if (ci_strcmp(name,"DATE")==0)
- current_date = read_date();
- else if (ci_strcmp(name,"COMPANY")==0)
- {
- read_name(name);
- check_company_name(name);
- }
- else if (ci_strcmp(name,"CLOSE")==0 ||
- ci_strcmp(name,"ADD")==0)
- {
- struct table *p, *q;
- int close = ci_strcmp(name,"CLOSE")==0;
- read_name(name);
- p = find_table_entry(name);
- if (source.c=='.')
- {
- read_character();
- if (source.c!='.') declare_error("Incomplete ellipsis");
- while (source.c=='.') read_character();
- read_name(name);
- q = find_table_entry(name);
- if (p->type!=ACCOUNT || q->type!=ACCOUNT)
- raise_error("Series of non-ledger amounts");
- }
- else q = p;
- while (1)
- {
- if (close) post(negative(account_balance(p)), p);
- else total = sum(total, account_balance(p));
- if (p==q) break;
- p = p->next;
- if (p==NULL) raise_error("Invalid group of ledger accounts");
- }
- }
- else if (ci_strcmp(name,"INTO")==0)
- {
- read_name(name);
- post(negative(balance), find_table_entry(name));
- }
- else if (ci_strcmp(name,"SUBTRACT")==0)
- {
- read_name(name);
- total = sum(total, negative(account_balance(find_table_entry(name))));
- }
- else if (ci_strcmp(name,"DEBIT")==0)
- {
- total = sum(total, read_amount());
- }
- else if (ci_strcmp(name,"CREDIT")==0)
- {
- total = sum(total, negative(read_amount()));
- }
- else if (ci_strcmp(name,"MESSAGE")==0)
- {
- skip_spaces();
- report(NULL,NULL,-1);
- putchar('\n');
- }
- else if (ci_strcmp(name,"INCLUDE")==0)
- {
- company_name_required();
- read_specs(name);
- journal(name);
- }
- else if (ci_strcmp(name,"READ LEDGER")==0)
- {
- company_name_required();
- read_specs(name);
- read_ledger(name);
- }
- else if (ci_strcmp(name,"WRITE LEDGER")==0)
- {
- company_name_required();
- read_specs(name);
- write_ledger(name);
- }
- else if (ci_strcmp(name,"REPORT")==0)
- {
- static char report_file[MAXIMUM_FILESPEC_LENGTH+1];
- int trim = 0;
- company_name_required();
- read_specs(name);
- if (source.c!=',') raise_error("Missing report file");
- read_character();
- read_specs(report_file);
- if (source.c==',')
- {
- read_character();
- trim = read_number();
- if (trim<0 || trim>AMOUNT_WIDTH-4)
- declare_error("Invalid trimming value");
- }
- report(name, report_file, trim);
- }
- else if (ci_strcmp(name,"TOTAL")==0)
- {
- struct table *p;
- read_name(name);
- p = look_for_table_entry(name);
- if (p==NULL) p = new_table_entry(name);
- p->type = AMOUNT;
- p->x.amount = total;
- total = 0;
- }
- else if (ci_strcmp(name,"TRIAL BALANCE")==0 ||
- ci_strcmp(name,"CONDENSED TRIAL BALANCE")==0)
- {
- int condensed = ci_strcmp(name,"CONDENSED TRIAL BALANCE")==0;
- struct table *p;
- amount_type debit_balance = 0;
- amount_type credit_balance = 0;
- char trial_balance_journal_name[MAXIMUM_NAME_LENGTH+1];
- company_name_required();
- read_specs(name);
- if (source.c==',')
- {
- read_character();
- read_name(trial_balance_journal_name);
- }
- else
- trial_balance_journal_name[0] = 0;
- open_output_file(name);
- if (trial_balance_journal_name[0]!=0)
- {
- write_string("Journal: ");
- write_string(
- trial_balance_journal_name);
- write_string("\n");
- }
- write_string("Company: ");
- write_string(company_name);
- write_string("\nDate: ");
- write_date(current_date);
- write_string("\n\n");
- for (p=first_table_entry; p!=NULL; p=p->next) if (p->type==ACCOUNT)
- {
- int credit = 0;
- amount_type balance = account_balance(p);
- if (iscredit(balance))
- {
- write_character(' ');
- credit = 1;
- balance = negative(balance);
- credit_balance = sum(credit_balance, balance);
- }
- else
- debit_balance = sum(debit_balance, balance);
- if (!iszero(balance) || !condensed)
- {
- write_name(p->name);
- if (credit)
- {
- write_character(' ');
- write_repeated_characters(' ',0);
- }
- write_amount(balance, 0);
- write_character('\n');
- }
- }
- write_name("*");
- write_repeated_characters('-',0);
- write_string(" ");
- write_repeated_characters('-',0);
- write_character('\n');
- write_name("* Totals");
- write_amount(debit_balance,0);
- write_string(" ");
- write_amount(credit_balance,0);
- write_character('\n');
- write_name("*");
- write_repeated_characters('=',0);
- write_string(" ");
- write_repeated_characters('=',0);
- write_character('\n');
- close_output_file();
- }
- else raise_error_with_name("Invalid command", name);
- }
- else
- {
- amount_type amount = read_amount();
- if (source.indented) amount = negative(amount);
- post(amount, find_table_entry(name));
- }
- skip_spaces();
- if (source.c!='*' && source.c!='\n' && source.c!=EOF)
- declare_error("Spurious or superfluous information on command line");
- }
- close_source_file();
- source = save_source;
- current_journal = save_journal;
- }
-
-
- void main(int argc, char **argv)
- {
- if (argc<2) declare_error("Missing journal file specifications");
- else
- {
- static char comline[129];
- /* get date from DOS */
- {
- struct date d;
- getdate(&d);
- current_date.month = d.da_mon;
- current_date.day = d.da_day;
- current_date.year = d.da_year-1980;
- if (current_date.year>2049-1980) current_date.year = 2049-1980;
- }
- /* reassmeble command line */
- {
- int i;
- char *s = comline;
- for (i=1; i<argc; i++)
- {
- char *t = argv[i];
- if (s!=comline) *s++ = ' ';
- while (*t!=0) *s++ = *t++;
- }
- *s = 0;
- }
- /* scan reassembled command line */
- {
- char *s = comline;
- while (*s!=0)
- {
- char *ss;
- while (*s==' ' || *s=='\t') s++;
- ss = s;
- if (*s=='[')
- {
- while (*s!=']' && *s!=0) s++;
- }
- else if (*s!=0)
- {
- while (*s!=' ' && *s!='\t' && *s!=0) s++;
- }
- if (*s!=0) *s++ = 0;
- journal(ss);
- }
- }
- }
- exit(err.level);
- }